package com.totoro.websocket;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.totoro.pojo.SuViceChat;
import com.totoro.service.ChatService;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.*;

import java.io.IOException;
import java.util.*;

/**
 * @author TOTORO
 * @date 2021/8/27 11:40
 */
@Component
@Service
public class MyWebSocketHandler implements WebSocketHandler{

    private final String SPLIT_STR = "我用来分割字符串";
    @Autowired
    ChatService chatService;

    /**
     * 当 MyWebSocketHandler 类被加载时就会创建该 Map
     */
    private static final Map<Integer, WebSocketSession> userSocketSessionMap;

    static {
        userSocketSessionMap = new HashMap<Integer, WebSocketSession>();
    }

    /**
     * 连接成功后
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session)
            throws Exception {
        System.out.println(session.getId()+"是sid");

        // 此处为 WebSocketSession，uid 是由拦截器已绑定好的，用于区分用户
        int uid = Integer.parseInt(session.getAttributes().get("uid").toString());
        // 绑定session
        // session根据键替换，因为所有页面都能够通信，考虑到一个页面切换的重新握手，会导致session发生变换，那么之前集合里的session会话就会关闭，所以需要根据之前的id重新加入一个最新的session进行通行
            userSocketSessionMap.put(uid, session);

        System.out.println(userSocketSessionMap.size());
    }

    /**
     * 消息处理
     */
    @Override
    public void handleMessage(WebSocketSession session,
                              WebSocketMessage<?> message) throws Exception {
        if (message.getPayloadLength() == 0){ return;}

        String jsonStr = message.getPayload().toString();
        // 将前端传回来的json字符串序列化
        ObjectMapper mapper = new ObjectMapper();
        JsonNode rootNode = mapper.readTree(jsonStr);
        // 分别从json中获取如下数据：聊天面板ID-发送信息-发送类型-发送人ID-接收人ID
        int suMainChatId = rootNode.get("suMainChatId").asInt();
        String sendMessage = rootNode.get("sendMessage").asText();
        int sendType = rootNode.get("sendType").asInt();
        int fromUid = rootNode.get("fromUid").asInt();
        int toUid = rootNode.get("toUid").asInt();
        // 封装成对象
        SuViceChat suViceChat = new SuViceChat(suMainChatId, sendMessage, sendType, fromUid, toUid, 1, 0);
        // 将此次发送的消息存进数据库-消息记录当中
        chatService.addChatMessage(suViceChat);
        // 先判断需要发送的用户是否在线，如果不在线，则不发送
        WebSocketSession webSocketSession = userSocketSessionMap.get(toUid);
        if(null == webSocketSession){
            return;
        }
        // 把消息发送给指定用户
        System.out.println("本次消息："+message+"\n 本次发送用户："+toUid);
        sendAssignUser(message, toUid);

//         自己定义的函数，发送给在线的所有人
//        sendMessageToAllUsers(message);

    }

    /**
     * 消息传输错误处理
     */
    @Override
    public void handleTransportError(WebSocketSession session,
                                     Throwable exception) throws Exception {

        String uid = session.getAttributes().get("uid").toString();
        if (session.isOpen()) {
            session.close();
        }
        System.out.println(uid + " 连接失败");
        userSocketSessionMap.remove(session);

    }

    /**
     * 关闭连接后
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session,
                                      CloseStatus closeStatus) throws Exception {

        String uid = session.getAttributes().get("uid").toString();
        System.out.println("UserWebSocket:" + uid + " close connection");
        Iterator<Map.Entry<Integer, WebSocketSession>> iterator = userSocketSessionMap.entrySet().iterator();
        // 移除
        while (iterator.hasNext()) {
            // 取值查询
            Map.Entry<Integer, WebSocketSession> entry = iterator.next();
            if (entry.getValue().getAttributes().get("uid") == uid) {
                iterator.remove();
                System.out.println("WebSocket in UserMap:" + uid + " removed");
            }
        }

    }

    @Override
    public boolean supportsPartialMessages() {
        return false;
    }

    @SneakyThrows
    private boolean sendAssignUser(WebSocketMessage message, int userId){
        WebSocketSession webSocketSession = userSocketSessionMap.get(userId);
        webSocketSession.sendMessage(message);
        return true;
    }

    /**
     * 发送给所有用户
     * @param message
     * @return
     */
    private boolean sendMessageToAllUsers(WebSocketMessage message) {
        boolean allSendSuccess = true;
        Set<Integer> clientIds = userSocketSessionMap.keySet();
        WebSocketSession session = null;
        for (Integer clientId : clientIds) {
            try {
                session = userSocketSessionMap.get(clientId);
                if (session.isOpen()) {
                    session.sendMessage(message);
                }
            } catch (IOException e) {
                e.printStackTrace();
                allSendSuccess = false;
            }
        }
        return allSendSuccess;
    }

}
